package com.fyzs.mp3recorder.wav

import android.media.AudioFormat
import android.os.Handler
import android.os.HandlerThread
import android.os.Looper
import android.util.Log
import androidx.annotation.IntDef
import androidx.annotation.IntegerRes
import androidx.fragment.app.FragmentStatePagerAdapter
import com.fyzs.mp3recorder.AudioRecorderFragment
import java.io.*
import java.lang.annotation.Retention
import java.lang.annotation.RetentionPolicy
import java.util.*
import java.util.concurrent.LinkedBlockingQueue

class Pcm2Wav {
    val TAG = "Pcm2Wav"
//    private val processThread = HandlerThread("encode").apply { start() }
//    private val processHandler = Handler(processThread.looper)

//    private val uiHandler = Handler(Looper.getMainLooper())


    var mProcessCallback: ProcessCallback? = null

    interface ProcessCallback {
        fun onFinished(path: String)
    }

    @Retention(RetentionPolicy.SOURCE)
    @IntDef(
        AudioFormat.ENCODING_PCM_8BIT,
        AudioFormat.ENCODING_PCM_16BIT
    )
    private annotation class PcmFormat {}


    var pcmSampleRate: Int = 0
    var pcmChannelNum: Int = 0

    var pcmEncodeFormat: Int = 0
    var pcmFormatBitCount = 16
    lateinit var sourceFile: File

    lateinit var outputFile: File

    fun setSampleRate(rate: Int) {
        pcmSampleRate = rate
    }

    fun setPcmChannel(n: Int) {
        pcmChannelNum = n
    }

    fun setPcmFormat(@PcmFormat format: Int) {
        pcmEncodeFormat = format
        when (pcmEncodeFormat) {
            AudioFormat.ENCODING_PCM_16BIT -> {
                pcmFormatBitCount = 16
            }
            AudioFormat.ENCODING_PCM_8BIT -> {
                pcmFormatBitCount = 8
            }
        }
    }

    fun setSource(path: String) {
        val sourceFile = File(path)

        if (!sourceFile.exists()) {
            throw IllegalAccessException("目标文件不存才")
        }

    }

    fun setSource(file: File) {
        sourceFile = file
    }

    fun setOutput(file: File) {
        outputFile = file
    }

    fun setOutput(path: String) {
        outputFile = File(path)
    }

    /**
     * 开始处理
     * RIFF
     * ID	0x00	4Byte	大端	'RIFF' (0x52494646)
     * Size	0x04	4Byte	小端	fileSize - 8
     * Type	0x08	4Byte	大端	'WAVE'(0x57415645)
     *
     * FMT
     * ID	0x00	4Byte	大端	'fmt ' (0x666D7420)
     * Size	0x04	4Byte	小端	16
     * AudioFormat	0x08	2Byte	小端	音频格式
     * NumChannels	0x0A	2Byte	小端	声道数
     * SampleRate	0x0C	4Byte	小端	采样率
     * ByteRate	0x10	4Byte	小端	每秒数据字节数
     * BlockAlign	0x14	2Byte	小端	数据块对齐
     * BitsPerSample	0x16	2Byte	小端	采样位数
     *
     * DATA
     * ID	0x00	4Byte	大端	'data' (0x64617461)
     * Size	0x04	4Byte	小端	N
     * Data	0x08	NByte	小端	音频数据
     * */
    fun start(): String? {
//        processHandler.post {
        //第一步 首先 根据PCM 参数 计算 WAV header
        //RIFF Block 共 12 byte
        val riffId = charArrayOf('R', 'I', 'F', 'F')
        val riffSize = littleEndianInt(sourceFile.length().toInt() + 44 - 8)//小端存储
        val riffType = charArrayOf('W', 'A', 'V', 'E')
        //fmt  Block 共 24byte
        val fmtId = charArrayOf('f', 'm', 't', ' ')
        val fmtSize =littleEndianInt(16)  //小端存储
        val fmtPcm =littleEndianShort(1)  //1 pcm 小端存储
        val fmtNC =littleEndianShort(2)
        val fmtSR = littleEndianInt(pcmSampleRate)
        val fmtBR =littleEndianInt((pcmSampleRate * pcmChannelNum * pcmFormatBitCount.div(8)))
        //data Block  8 byte
        val dataId = charArrayOf('d', 'a', 't', 'a')
        val dataSize =littleEndianInt(sourceFile.length().toInt())
        val wavOutputStream = DataOutputStream(outputFile.outputStream())

        /*写入 riff  block */
        //写入 RIFF id 4 Byte
        Log.i(TAG, "=================RIFF===================")
        for (c in riffId) {
            wavOutputStream.writeByte(c.code)
        }
        Log.i(TAG, "RIFF ID : ${riffId[0]}${riffId[1]}${riffId[2]}${riffId[3]}")

        //写入 RIFF size 4byte
        //转为小端模式
        Log.i(TAG, "RIFF SIZE ${sourceFile.length().toInt() + 44 - 8}")
        wavOutputStream.write(riffSize)
        //写入 RIFF type 4 Byte
        for (c in riffType) {
            wavOutputStream.writeByte(c.code)
        }
        Log.i(TAG, "RIFF ID : ${riffType[0]}${riffType[1]}${riffType[2]}${riffType[3]}")

        Log.i(TAG, "=================RIFF END===================")
        /*写入 Fmt block */
        //写入 Fmt ID 4 Byte
        Log.i(TAG, "=================FMT===================")
        for (c in fmtId) {
            wavOutputStream.writeByte(c.code)
        }
        Log.i(TAG, "FMT ID : ${fmtId[0]}${fmtId[1]}${fmtId[2]}${fmtId[3]}")
        //写入 FMT size 4 Byte
        wavOutputStream.write(fmtSize)
        Log.i(TAG, "FMT SIZE:${16}")
        //写入 Fmt AudioFormat 2 Byte
        wavOutputStream.write(fmtPcm)
        Log.i(TAG, "FMT SIZE:${1}")
        //写入Fmt NumChannels 2 Byte
        wavOutputStream.write(fmtNC)
        Log.i(TAG, "FMT Channels :${2}")
        //写入 Fmt Sample Rate  4Byte
        wavOutputStream.write(fmtSR)
        Log.i(TAG, "FMT sample rate :${pcmSampleRate}")
        //写入Fmt Byte per Second 4 Byte
        wavOutputStream.write(fmtBR)
        Log.i(TAG, "FMT byte rate :${(pcmSampleRate * pcmChannelNum * pcmFormatBitCount.div(8))}")
        //写入 Fmt Block Align
        Log.i(TAG, "align: 2 0")
        val fmtAlign:Short = 2
        wavOutputStream.write(littleEndianShort(fmtAlign))
        //写入 Fmt Bit perSample
        Log.i(TAG, "start: 16 0")
        val pcmBitCount = littleEndianShort(16)
        wavOutputStream.write(pcmBitCount)
        Log.i(TAG, "=================FMT  END===================")
        /*写入 data block*/
        //写入  dataId
        for (c in dataId) {
            wavOutputStream.writeByte(c.code)
        }
        Log.i(TAG, "data id:${dataId[0]}${dataId[1]}${dataId[2]}${dataId[3]}")
        //写入 dataSize
        Log.i(TAG, "data size: ${sourceFile.length().toInt()}")
        wavOutputStream.write(dataSize)
        //写入PCM 原始音频数
        val pcmInputStream = DataInputStream(FileInputStream(sourceFile))

        while (pcmInputStream.available()>0){
            val readShort = pcmInputStream.readShort()
            //转为小端存储
            wavOutputStream.write(littleEndianShort(readShort))
        }
        pcmInputStream.close()
        wavOutputStream.flush()
        wavOutputStream.close()
        return outputFile.absolutePath
    }

    /**
     * 小端模式
     * */
    private fun toLittleEndian(){

    }

     fun littleEndianInt(v: Int): ByteArray {
        //获取高 12 位
        val LOW_0:Byte = (v.shl(Byte.SIZE_BITS*3)).shr(Byte.SIZE_BITS*3).toByte()
        val LOW_1:Byte =( v.shl(Byte.SIZE_BITS*2)).shr(Byte.SIZE_BITS*3).toByte()
        val HIGH_0:Byte=(v.shl(Byte.SIZE_BITS*1)).shr(Byte.SIZE_BITS*3).toByte()
        val HIGH_1:Byte=v.shr(Byte.SIZE_BITS*3).toByte()

        return byteArrayOf(LOW_0, LOW_1, HIGH_0, HIGH_1)
    }
     fun littleEndianShort(v: Short): ByteArray {
        //获取高 12 位
        val LOW:Byte = (v.toInt().shl(Byte.SIZE_BITS)).shr(Byte.SIZE_BITS).toByte()
        val HIGH:Byte=(v.toInt().shr(Byte.SIZE_BITS)).toByte()

        return byteArrayOf(LOW,HIGH)
    }

}